package com.mzj.saas.electronicVisa.fadada.callback;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.fasc.open.api.utils.crypt.FddCryptUtil;
import com.fasc.open.api.v5_1.res.org.EmployeeInfo;
import com.fasc.open.api.v5_1.res.org.GetEntityListRes;
import com.haixiaoke.saas.repository.electronicVisa.service.FadadaElectronicVisaService;
import com.haixiaoke.saas.repository.pojo.ElectronicSigningContract;
import com.haixiaoke.saas.repository.pojo.OrgElectronicVisa;
import com.haixiaoke.saas.repository.service.IElectronicSigningContractService;
import com.haixiaoke.saas.repository.service.IOrgElectronicVisaService;
import com.mzj.saas.manager.AsyncManager;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.web.bind.annotation.*;

import java.util.*;

/**
 * 法大大电子签回调
 *
 * @author qixi
 * @date 2023/12/21
 */
@RestController
@RequestMapping("/electronicVisa/fadada/callback")
@Slf4j
public class FadadaCallbackController {


    @Autowired
    private FadadaElectronicVisaService fadadaElectronicVisaService;

    @Autowired
    private IOrgElectronicVisaService orgElectronicVisaService;

    @Autowired
    private IElectronicSigningContractService electronicSigningContractService;

    /**
     * 法大大电子签回调
     * <a>https://dev.fadada.com/api-doc/DKO6NVNYH3/UMZTMGU1FSROCUQJ/5-1</a>
     */
    @ResponseBody
    @PostMapping
    public String fddEventCallback(@RequestHeader HttpHeaders headers,
                                   @RequestParam("bizContent") String bizContent) {
        // appSecret，由开发者登陆到法大大官网，在应用管理管理中点击应用详情里面获取
        String appSecret = fadadaElectronicVisaService.APPSECRET;
        // 获取请求头参数
        String appId = headers.getFirst("X-FASC-App-Id");
        String signType = headers.getFirst("X-FASC-Sign-Type");
        String sign = headers.getFirst("X-FASC-Sign");
        String timestamp = headers.getFirst("X-FASC-Timestamp");
        // 事件名称，开发者可以根据不同事件名称去解析bizContent的值，实现不同的逻辑
        String event = headers.getFirst("X-FASC-Event");
        String nonce = headers.getFirst("X-FASC-Nonce");
        // 验签
        Map<String, String> paramMap = new HashMap<>();
        paramMap.put("X-FASC-App-Id", appId);
        paramMap.put("X-FASC-Sign-Type", "HMAC-SHA256");
        paramMap.put("X-FASC-Timestamp", timestamp);
        paramMap.put("X-FASC-Nonce", nonce);
        paramMap.put("X-FASC-Event", event);
        paramMap.put("bizContent", bizContent);
        // 参数排序，ascii码排序
        String sortParam = FddCryptUtil.sortParameters(paramMap);
        // 生成签名后可以进行校验
        try {
            String signature = FddCryptUtil.sign(sortParam, timestamp, appSecret);
            if (!signature.equals(sign)) {
                // log.error("日志记录，签名失败");
                // 为了不重复接收该请求，建议这里返回success，返回success后这条消息法大大将中断重试回调机制
                return "{\"msg\":\"success\"}";
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        Map<String, Object> map = JSON.parseObject(bizContent, Map.class);

        AsyncManager.me().execute(new TimerTask() {
            @Override
            public void run() {
                disposeCallback(event, map);
            }
        });
        return "{\"msg\":\"success\"}";
    }

    /**
     * 处理回调
     *
     * @param event 事件id
     * @param map
     * <a>https://dev.fadada.com/api-doc/HZRSAZQXZR/0T8MZCFRRZTU646K/5-1</a>
     */
    private void disposeCallback(String event, Map<String, Object> map) {
        if (ObjectUtil.isNull(map)) {
            log.error("回调事件，map为空");
            return;
        }
        switch (event) {
            // 企业用户授权事件
            case "corp-authorize":
                log.info("企业用户授权事件 data:{}", map);
                this.enterpriseAuth(map);
                break;
            case "sign-task-signed":
                log.info("签署任务参与方签署成功事件 data:{}", map);
                this.signed(map);
                break;
            case "sign-task-finished":
                log.info("签署任务完成事件 data:{}", map);
                this.finished(map);
                break;
            case "sign-task-sign-rejected":
                log.info("参与方拒签 data:{}", map);
                this.visaRejected(map);
                break;
            case "sign-task-canceled":
                log.info("签署任务撤销 data:{}", map);
                this.canceled(map);
                break;
            case "sign-task-expire":
                log.info("签署任务逾期 data:{}", map);
                this.expire(map);
                break;
        }

    }

    private void expire(Map<String, Object> map) {
        String signTaskId = map.get("signTaskId").toString();
        ElectronicSigningContract electronicSigningContract = electronicSigningContractService.selectElectronicSigningContractByFlowId(signTaskId);
        if (ObjectUtil.isNull(electronicSigningContract)) {
            log.error("签署任务逾期事件，签署任务不存在，signTaskId:{}", signTaskId);
            return;
        }

        String signTaskStatus = map.get("signTaskStatus").toString();
        // expired：已逾期
        if ("expired".equals(signTaskStatus)){
            electronicSigningContract.setContractState(ElectronicSigningContract.CONTRACT_STATE_OVERDUE);
            electronicSigningContract.setUpdateTime(DateUtil.date());
            electronicSigningContractService.updateElectronicSigningContract(electronicSigningContract);
        }
    }

    /**
     * 签署任务撤销
     * @param map
     */
    private void canceled(Map<String, Object> map) {
        String signTaskId = map.get("signTaskId").toString();
        ElectronicSigningContract electronicSigningContract = electronicSigningContractService.selectElectronicSigningContractByFlowId(signTaskId);
        if (ObjectUtil.isNull(electronicSigningContract)) {
            log.error("参与方拒签事件，签署任务不存在，signTaskId:{}", signTaskId);
            return;
        }
        String signTaskStatus = map.get("signTaskStatus").toString();
        if ("task_terminated".equals(signTaskStatus)){
            electronicSigningContract.setContractState(ElectronicSigningContract.CONTRACT_STATE_STOP);
            Object terminationNote = map.get("terminationNote");
            if (ObjectUtil.isNotNull(terminationNote)){
                electronicSigningContract.setRemark(terminationNote.toString());
            }
            electronicSigningContractService.updateElectronicSigningContract(electronicSigningContract);
        }
    }

    /**
     * 拒签事件
     * @param map
     */
    private void visaRejected(Map<String, Object> map) {

        String actorId = map.get("actorId").toString();
        if (StrUtil.equals("个人方", actorId)) {
            String signTaskId = map.get("signTaskId").toString();
            ElectronicSigningContract electronicSigningContract = electronicSigningContractService.selectElectronicSigningContractByFlowId(signTaskId);
            if (ObjectUtil.isNull(electronicSigningContract)) {
                log.error("参与方拒签事件，签署任务不存在，signTaskId:{}", signTaskId);
                return;
            }
            electronicSigningContract.setContractState(ElectronicSigningContract.CONTRACT_STATE_STOP);
            electronicSigningContract.setUpdateTime(DateUtil.date());
            electronicSigningContractService.updateElectronicSigningContract(electronicSigningContract);
        }
    }

    public void finished(Map<String, Object> map) {

        String signTaskStatus = map.get("signTaskStatus").toString();
        // sign_progress：签署中 (签署参与方进行签署)
        // sign_completed：签署已完成 (签署所有参与方均已签署完成)
        // task_finished：任务已完成 (签署任务已成功结束)
        if (StrUtil.equals("task_finished", signTaskStatus)) {
            String signTaskId = map.get("signTaskId").toString();
            ElectronicSigningContract electronicSigningContract = electronicSigningContractService.selectElectronicSigningContractByFlowId(signTaskId);
            if (ObjectUtil.isNull(electronicSigningContract)) {
                log.error("签署任务参与方签署成功事件，签署任务不存在，signTaskId:{}", signTaskId);
                return;
            }
            electronicSigningContract.setContractState(ElectronicSigningContract.CONTRACT_STATE_SIGN_OK);
            String eventTime = map.get("eventTime").toString();
            electronicSigningContract.setContractCompletionTime(new Date(Long.parseLong(eventTime)));
            electronicSigningContractService.updateElectronicSigningContract(electronicSigningContract);


        }
    }

    /**
     * 签署任务参与方签署成功事件
     *
     * @param map
     */
    private void signed(Map<String, Object> map) {

        String signTaskStatus = map.get("signTaskStatus").toString();
        // sign_progress：签署中 (签署参与方进行签署)
        // sign_completed：签署已完成 (签署所有参与方均已签署完成)
        // task_finished：任务已完成 (签署任务已成功结束)
        if (StrUtil.equals("sign_progress", signTaskStatus)) {
            String signTaskId = map.get("signTaskId").toString();
            ElectronicSigningContract electronicSigningContract = electronicSigningContractService.selectElectronicSigningContractByFlowId(signTaskId);
            if (ObjectUtil.isNull(electronicSigningContract)) {
                log.error("签署任务参与方签署成功事件，签署任务不存在，signTaskId:{}", signTaskId);
                return;
            }
            String actorId = map.get("actorId").toString();
            if (StrUtil.equals("个人方", actorId)) {
                electronicSigningContract.setContractState(ElectronicSigningContract.CONTRACT_STATE_SIGN_OK);
            }
            if (StrUtil.equals("企业方", actorId)) {
                electronicSigningContract.setContractState(ElectronicSigningContract.CONTRACT_STATE_TENANT_SIGN);
            }
            electronicSigningContractService.updateElectronicSigningContract(electronicSigningContract);
        }


    }

    /**
     * 企业用户授权事件
     *
     * @param map
     */
    public void enterpriseAuth(Map<String, Object> map) {
        String authResult = map.get("authResult").toString();
        if ("success".equals(authResult)) {
            String clientCorpId = map.get("clientCorpId").toString();
            String openCorpId = map.get("openCorpId").toString();
            String[] split = clientCorpId.split("_");
            if (split.length != 3) {
                log.error("企业用户授权事件，clientCorpId格式错误，clientCorpId:{}", clientCorpId);
                return;
            }
            Long orgId = Long.parseLong(split[2]);
            String orgName = split[0];
            OrgElectronicVisa orgElectronicVisa = new OrgElectronicVisa();
            orgElectronicVisa.setOrgId(orgId);
            orgElectronicVisa.setProxyOrganizationOpenId(clientCorpId);
            orgElectronicVisa.setOpenId(openCorpId);
            orgElectronicVisa.setOrgName(orgName);
            try {
                List<EmployeeInfo> corpMemberList = fadadaElectronicVisaService.getCorpMemberList(orgElectronicVisa);
                EmployeeInfo employeeInfo = corpMemberList.get(0);
                Long memberId = employeeInfo.getMemberId();
                orgElectronicVisa.setProxyOperatorOpenid(memberId.toString());

                List<GetEntityListRes> corpEntityList = fadadaElectronicVisaService.getCorpEntityList(openCorpId);
                GetEntityListRes getEntityListRes = corpEntityList.get(0);
                orgElectronicVisa.setOrganizationName(getEntityListRes.getCorpName());
                orgElectronicVisa.setUSCC(getEntityListRes.getCorpIdentNo());
                orgElectronicVisa.setCreateTime(new Date());
                orgElectronicVisaService.insertOrgElectronicVisa(orgElectronicVisa);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }


}
